package com.qxt.prize.services;

import com.qxt.prize.forms.PrizeForm;
import com.qxt.prize.models.Prize;
import com.qxt.prize.repositories.PrizeRepository;
import jakarta.inject.Inject;
import jakarta.inject.Named;
import org.springframework.transaction.support.TransactionTemplate;
import top.moirae.core.AbstractEither;
import top.moirae.core.ErrorMessage;
import top.moirae.core.Left;
import top.moirae.core.Right;
import top.moirae.repository.PaginationData;
import top.moirae.repository.PaginationForm;
import top.moirae.security.forms.IdsForm;

import java.util.Arrays;

@Named
public class PrizeService {
    private final PrizeRepository prizeRepository;
    private final TransactionTemplate transactionTemplate;

    @Inject
    public PrizeService(PrizeRepository prizeRepository, @Named("BUSINESS_TT") TransactionTemplate transactionTemplate) {
        this.prizeRepository = prizeRepository;
        this.transactionTemplate = transactionTemplate;
    }

    public AbstractEither<ErrorMessage, Long> create(long optUserId, PrizeForm.Create form) {
        return Right.apply(prizeRepository.create(optUserId, form));
    }

    public AbstractEither<ErrorMessage, Prize> get(long id) {
        return prizeRepository.option(id).toRight(Prize.Errors.NOT_FOUND);
    }

    public AbstractEither<ErrorMessage, Long> update(long optUserId, long id, PrizeForm.Update form) {
        return Right.apply(prizeRepository.update(optUserId, id, form));
    }

    public AbstractEither<ErrorMessage, Long> minusInventory(long id) {
        return get(id).fold(Left::apply, prize -> {
            // 奖品无限供应
            if (prize.getQuantity() == null) {
                return Right.apply(200L);
            }
            // 否则库存-1
            return Right.apply(prizeRepository.minusInventory(id, Math.abs(prize.getQuantity() - 1)));
        });
    }

    public AbstractEither<ErrorMessage, Long> changePublishState(long id) {
        return get(id).fold(Left::apply, prize -> {
            if (prize.getPublishAt() == null) {
                return Right.apply(prizeRepository.changePublishStateOn(id));
            }
            return Right.apply(prizeRepository.changePublishStateOff(id));
        });
    }

    public AbstractEither<ErrorMessage, Integer> delete(IdsForm ids) {
        return transactionTemplate.execute(status -> Right.apply(Arrays.stream(ids.getIds()).mapToInt(prizeRepository::delete).sum()));
    }

    public AbstractEither<ErrorMessage, PaginationData<Prize>> list(PrizeForm.Search form, PaginationForm paginationForm) {
        return Right.apply(prizeRepository.list(form, paginationForm));
    }

    public AbstractEither<ErrorMessage, Boolean> isExits(long id) {
        return Right.apply(prizeRepository.isExits(id));
    }
}

